package com.acme.concurrent.pool.impl;

import com.acme.concurrent.pool.DataSource;
import com.acme.concurrent.pool.DataSourceException;
import com.acme.concurrent.pool.NonBlockingPool;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;

public class SimpleBlockingQueuePool<T> implements NonBlockingPool<T> {
    private final Set<T> storage;
    private final BlockingQueue<T> queue;

    public SimpleBlockingQueuePool(DataSource<T> dataSource, int max) throws InterruptedException, DataSourceException {
        storage = new HashSet<T>();
        queue = new ArrayBlockingQueue<T>(max);
        for(int i = 0; i < max; i++){
            T inst = dataSource.newInstance();
            storage.add(inst);
            queue.put(inst);
        }
        if (storage.size() != max) {
            throw new RuntimeException("DataSource created two or more similar objects");
        }
    }

    @Override
    public synchronized T get() throws InterruptedException {
        return queue.take();
    }

    @Override
    public synchronized void  release(T object) {
        try {
            if(storage.contains(object) && !queue.contains(object)){
                queue.put(object);
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public synchronized T tryGet() {
        return queue.poll();
    }

    @Override
    public synchronized T tryGet(long timeout, TimeUnit timeUnit) throws InterruptedException {
        return queue.poll(timeout, timeUnit);
    }

}